import { Direction, convertToGrid } from '../constants'

export default class Snake {
  private readonly body: number[] = []
  constructor(init: number[]) {
    init.forEach(index => this.body.push(index))
    console.log(this.body, 'body')
  }
  get head() {
    return this.body[0]
  }
  get tail() {
    return this.body[this.body.length - 1]
  }
  get length() {
    return this.body.length
  }

  nextHead(direction: Direction, width: number, height: number) {
    let onLastPosition: boolean
    switch (direction) {
      case Direction.RIGHT:
        onLastPosition = (this.head + 1) % width === 0
        return onLastPosition ? this.head + 1 - width : this.head + 1
      case Direction.LEFT:
        onLastPosition = this.head % width === 0
        return onLastPosition ? this.head + width - 1 : this.head - 1
      case Direction.UP:
        onLastPosition = this.head < width
        return onLastPosition
          ? this.head + width * (height - 1)
          : this.head - width
      case Direction.DOWN:
        return (this.head + width) % (width * height)
    }
  }

  move(ateCandy: boolean, newHeadIndex: number) {
    if (!ateCandy) this.body.pop()
    this.body.unshift(newHeadIndex)
  }

  occupiesBoardIndex(index: number) {
    return this.body.slice(0, this.body.length - 1).includes(index)
  }

  movementDirection(width: number, height: number) {
    const first = this.body[0]
    const second = this.body[1]
    const { row: firstRow, column: firstColumn } = convertToGrid(first, width)
    const { row: secondRow, column: secondColumn } = convertToGrid(
      second,
      width
    )
    const lastRow = height - 1
    const lastColumn = width - 1
    if (firstColumn === lastColumn && secondColumn === 0) return Direction.LEFT
    if (firstColumn === 0 && secondColumn === lastColumn) return Direction.RIGHT
    if (firstRow === 0 && secondRow === lastRow) return Direction.DOWN
    if (firstRow === lastRow && secondRow === 0) return Direction.UP

    if (firstRow > secondRow) return Direction.DOWN
    if (firstRow < secondRow) return Direction.UP
    if (firstColumn > secondColumn) return Direction.RIGHT
    if (firstColumn < secondColumn) return Direction.LEFT

    throw new Error('what happened!!!!')
  }

  invertedMovementDirection(width: number, height: number) {
    const direction = this.movementDirection(width, height)
    switch (direction) {
      case Direction.LEFT:
        return Direction.RIGHT
      case Direction.RIGHT:
        return Direction.LEFT
      case Direction.UP:
        return Direction.DOWN
      case Direction.DOWN:
        return Direction.UP
    }
  }
}
